package com.atguigu.gmall.index.config;

import com.atguigu.gmall.common.bean.ResponseVo;
import com.atguigu.gmall.index.feign.GmallPmsClient;
import com.atguigu.gmall.pms.entity.CategoryEntity;
import org.redisson.Redisson;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.Duration;
import java.util.List;

@Configuration
public class RedisConfig {
    @Resource
    RedisTemplate redisTemplate;
    @Resource
    GmallPmsClient gmallPmsClient;
    //初始化布隆过滤器 并存入有下一级分类数据的一级分类id
    @Bean
    public RBloomFilter<Long> rBloomFilter(RedissonClient redissonClient){
        RBloomFilter<Long> bloomFilter = redissonClient.getBloomFilter("bloom:index:cates");
        if(bloomFilter.isExists()){
            bloomFilter.delete();
            bloomFilter = redissonClient.getBloomFilter("bloom:index:cates");
        }
        //期望元素数量 可以从数据库中查询
        //1、查询parent_id为0的分类数据
        ResponseVo<List<CategoryEntity>> responseVo = gmallPmsClient.hasSubs();
        List<CategoryEntity> categoryEntities = responseVo.getData();
        if(!CollectionUtils.isEmpty(categoryEntities)){
            bloomFilter.tryInit(categoryEntities.size() , 0.03);
            //2、如果分类下一级分类不为空 才需要查询下一级分类数据 否则不用查询
            for (int i = 0; i < categoryEntities.size(); i++) {
                if(categoryEntities.get(i).isChildren()){
                    bloomFilter.add(categoryEntities.get(i).getId());
                }
            }
        }
        //如果pms修改了category数据： 可以通过mq同步数据
        // 也可以通过定时任务： 每天凌晨删除之前的布隆过滤器 重新初始化
        return bloomFilter;
    }

    //配置RedisonClient对象
    @Bean
    public RedissonClient redissonClient(){
        Config config = new Config();
        config.useSingleServer()//连接单实例的redis
            //reids地址
            .setAddress("redis://192.168.1.171:6379");
        //配置redisson看门狗 续期时长 默认30s
//        config.setLockWatchdogTimeout()
        return Redisson.create(config);
    }


    @PostConstruct
    public void init(){
        //配置键和值的序列化器
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
    }
    //LettuceConnectionFactory factory reids连接工厂
    // 必须整合commons-pool2 redis连接池 并配置
    @Bean
    public CacheManager cacheManager(LettuceConnectionFactory factory){
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                    .entryTtl(Duration.ofMinutes(60))
//                    .disableCachingNullValues()
                    .serializeKeysWith(RedisSerializationContext.SerializationPair
                            .fromSerializer(new StringRedisSerializer()))
                    .serializeValuesWith(RedisSerializationContext.SerializationPair
                            .fromSerializer(new GenericJackson2JsonRedisSerializer()))
                ;
        return RedisCacheManager.builder(factory).cacheDefaults(config).build();
    }

}
